home *** CD-ROM | disk | FTP | other *** search
- // DEBUG_SCREENS for message-box progress indicators
- // FAKE_LAUNCHES for message boxes instead of actual launches
- // SHOW_LAUNCHDATA for quick display just before prog launch -- works only if FAKE_LAUNCHES *not* specified
- // CHANGE_DIR to change directory to entry's default before launch attempted
- #include<windows.h>
- #include<commdlg.h>
- #include"wstring.hpp"
- #include"itemdata.hpp"
- #include"resource.h"
- #include"ini.hpp"
- #include<string.h>
- #include<ctype.h>
- #ifndef FAKE_LAUNCHES
- #include<direct.h>
- #endif
-
- #define IDM_GETSTARTED 1
-
- #define IDM_ABOUT 1001
- #define IDM_HELP 1002
- #define IDM_ONTOP 1003
- #define IDM_MYSYSCOMMANDS 1010
-
- #define BUTTON_WIDTH (icon_width+5)
-
- IniFile ini;
- GroupFile gf;
- #ifdef DEBUG_SCREENS
- WinMessageString screen;
- #endif
- WinMessageString errscreen;
- const int SCRATCH=256;
- unsigned int winver; // windows version
- char scratch[SCRATCH+1];
- static char WindowTitle[256];
- static char szFile[256]; // filename for .GRP file
- static HWND main_hwnd=NULL;
- static HINSTANCE main_hinst=NULL;
- static char AppTitle[]="ButtonGo";
- static char AppClassName[]="ButtonGoDeurbrouckClass";
- static char copyright[]=
- "BTNGO.EXE 1.0\n"
- "Program Launching Utility\n"
- "Copyright ⌐ 1993 John Deurbrouck\n\n"
- "First published in PC Magazine September 28, 1993\n";
- static char helpstring[]=
- "BTNGO conveniently displays the icons from any Program Manager group "
- "and allows you to launch them with a single mouse click.\n\n"
- "If started with a .GRP file specified on the command line, BTNGO can operate under "
- "Windows 3.0 and later. Otherwise, BTNGO requires COMMDLG.DLL to run under 3.0.\n\n"
- "See PC Magazine, September 28, 1993 (Vol. 12 No. 15) for more details. Support is also available "
- "on ZiffNet. From Compuserve, GO ZNT:UTILFORUM.";
- static char too_many_icons[]=
- "The group you have loaded has too many icons to display, "
- "so some of your icons may not be visible. "
- "No damage has occurred, and you may use the icons you can see.\n\n"
- "You can fix this by removing less-important items from the group, or by "
- "creating another group file and moving some icons from this group "
- "to the new one.";
- static LPSTR command_line_pointer;
- static HMENU gm=NULL; // system menu for main window
- static HBITMAP hbmUp=NULL,hbmDown=NULL,hbmNow=NULL; // for painting the main window
- static unsigned int max_index_added=0;
- static int show_parameter; // for call to ShowWindow, parm passed into WinMain
- static int actual_buttons=0; // number buttons on button bar
- static int icon_height,icon_width,bitmap_width,bitmap_height;
- static int mouse_down=0,mouse_button_number=-1,ok_to_launch; // used to drive mouse handling
- static int should_save_position_data=0,got_position_data,best_ontop=1,best_x,best_y; // used for .INI file handling
-
- void GetFilenameFromCmdLine(LPSTR cmdline,char *winpath,char *filename);
- long FAR PASCAL __export MainWndProc(HWND,UINT,UINT,LONG);
- int GetFileDataLoaded(LPSTR cmdline);
- int CreateBitmaps(void);
- int button_mouse_is_in(LONG lParam);
- void restore_mouse_normalcy(void);
- void get_right_bitmap(HDC hdc);
- #ifdef FAKE_LAUNCHES
- char *show_exe_data(int offset);
- #else
- void start_program(int offset);
- #endif
-
- int PASCAL WinMain(HINSTANCE hinstCurrent,HINSTANCE hinstPrevious,LPSTR lpszCmdLine,int nCmdShow){
- if(!hinstPrevious){
- WNDCLASS wc;
- wc.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
- wc.lpfnWndProc=MainWndProc;
- wc.cbClsExtra=0;
- wc.cbWndExtra=0;
- wc.hInstance=hinstCurrent;
- wc.hIcon=LoadIcon(hinstCurrent,MAKEINTRESOURCE(IDI_APPICON));
- wc.hCursor=LoadCursor(NULL,IDC_ARROW);
- wc.hbrBackground=NULL;
- wc.lpszMenuName=NULL;
- wc.lpszClassName=AppClassName;
- RegisterClass(&wc);
- }
- {
- DWORD ver=GetVersion();
- winver=LOBYTE(LOWORD(ver));
- winver<<=8;
- winver|=HIBYTE(LOWORD(ver));
- }
- command_line_pointer=lpszCmdLine;
- main_hinst=hinstCurrent;
- show_parameter=nCmdShow;
- ini.set_instance(hinstCurrent);
- main_hwnd=CreateWindow(AppClassName,AppTitle,
- WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX,
- CW_USEDEFAULT,CW_USEDEFAULT, // X,Y coords
- CW_USEDEFAULT,CW_USEDEFAULT, // x,y extents
- HWND_DESKTOP,NULL,hinstCurrent,NULL);
- #ifdef DEBUG_SCREENS
- screen.SetHwndParent(main_hwnd);
- #endif
- errscreen.SetHwndParent(main_hwnd);
- MSG msg;
- while(GetMessage(&msg,NULL,0,0)){
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
- }
-
- static void GetFilenameFromCmdLine(LPSTR cmdline,char *winpath,char *filename){
- LPSTR string_start;
- int got_pathchars=0,got_goodchars=0,got_whitespace=0;
- if(cmdline==NULL)return;
- while(*cmdline){ // scan, find filename start, look for '\\' and ':'
- if(isgraph(*cmdline)){
- if(got_whitespace){
- errscreen<<"Too many command line arguments";
- errscreen.show();
- return;
- }
- if(!got_goodchars){
- got_goodchars=1;
- string_start=cmdline;
- }
- if(*cmdline=='\\'||*cmdline==':')got_pathchars=1;
- if(*cmdline=='*'||*cmdline=='?'){
- errscreen<<"Can't use wildcards in command line arguments";
- errscreen.show();
- return;
- }
- }
- else{
- if(got_goodchars)got_whitespace=1;
- }
- cmdline++;
- }
- if(!got_goodchars)return; // no filename
- if(!got_pathchars){ // insert Windows dir, normal place for .GRP
- lstrcpy(filename,winpath);
- cmdline=filename;
- while(*cmdline)cmdline++;
- if(cmdline[-1]!='\\'){*cmdline++='\\';*cmdline=0;}
- lstrcat(filename,string_start);
- }
- else lstrcpy(filename,string_start);
- // now scan off any whitespace at end of filename
- cmdline=filename;
- while(*cmdline)cmdline++;
- cmdline--;
- while(!isgraph(*cmdline))*cmdline--=0;
- }
- long FAR PASCAL __export MainWndProc(HWND hwnd,UINT message,UINT wParam,LONG lParam){
- switch(message){
- case WM_CREATE:
- PostMessage(hwnd,WM_COMMAND,IDM_GETSTARTED,0L);
- return 0;
- case WM_COMMAND:
- switch(wParam){
- case IDM_GETSTARTED:
- gm=GetSystemMenu(main_hwnd,FALSE);
- DeleteMenu(gm,SC_SIZE,MF_BYCOMMAND);
- DeleteMenu(gm,SC_MAXIMIZE,MF_BYCOMMAND);
- AppendMenu(gm,MF_SEPARATOR,0,NULL);
- if(winver>=0x30A)AppendMenu(gm,MF_STRING,IDM_ONTOP,"Always on Top");
- AppendMenu(gm,MF_STRING,IDM_ABOUT,"About...");
- AppendMenu(gm,MF_STRING,IDM_HELP,"Help...");
- if(!GetFileDataLoaded(command_line_pointer)||
- !gf.get_icon_dimensions(icon_height,icon_width)||
- !CreateBitmaps()){
- PostMessage(hwnd,WM_DESTROY,0,0L);
- return 0;
- }
- if(gf.get_group_name()!=NULL){
- wsprintf(WindowTitle,"%s - %s",(LPSTR)AppTitle,gf.get_group_name());
- }
- else lstrcpy(WindowTitle,AppTitle);
- gf.done_with_bitmaps();
- SetWindowText(hwnd,WindowTitle);
- should_save_position_data=1;
- got_position_data=ini.get_screen_numbers(szFile,best_x,best_y,best_ontop);
- if(winver>=0x30A&&best_ontop)PostMessage(hwnd,WM_SYSCOMMAND,IDM_ONTOP,0L);
- int window_width=GetSystemMetrics(SM_CXBORDER)*2+bitmap_width;
- int window_height=GetSystemMetrics(SM_CYCAPTION)+bitmap_height+GetSystemMetrics(SM_CYBORDER);
- /*
- ok, someone changing from 1024x768 to 800x600 drivers might 'lose' the
- window so let's be sure the window's at least partially onscreen.
- if at least one pixel of the caption area is onscreen, the window
- can be grabbed and moved, so let's check for that
- */
- if(got_position_data)for(;;){
- got_position_data=0; // so can break on errors
- int capt_left=best_x+GetSystemMetrics(SM_CXBORDER)+GetSystemMetrics(SM_CXSIZE)+2;
- int capt_right=best_x+window_width-GetSystemMetrics(SM_CXSIZE)-2;
- int x_size=GetSystemMetrics(SM_CXSCREEN);
- if(!(capt_left<0&&capt_right>=x_size)){ // ok, straddles screen
- if(capt_right<0)break;
- if(capt_left>=x_size)break;
- }
- int capt_top=best_y+GetSystemMetrics(SM_CYBORDER)+2;
- int capt_bottom=best_y+GetSystemMetrics(SM_CYCAPTION)-2;
- int y_size=GetSystemMetrics(SM_CYSCREEN);
- if(capt_top>=y_size)break;
- if(capt_bottom<0)break;
- got_position_data=1;
- break;
- }
- if(got_position_data){
- SetWindowPos(hwnd,0,best_x,best_y,
- window_width,window_height,
- SWP_NOACTIVATE|SWP_NOZORDER);
- }
- else{
- SetWindowPos(hwnd,0,0,0,
- window_width,window_height,
- SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
- }
- int window_is_truncated=0;
- {
- RECT temprect;
- GetWindowRect(hwnd,&temprect);
- if((temprect.right-temprect.left)!=window_width){
- window_is_truncated=1;
- }
- }
- ShowWindow(hwnd,show_parameter);
- UpdateWindow(hwnd);
- if(window_is_truncated){
- MessageBox(hwnd,too_many_icons,"Window Creation Error",MB_OK);
- }
- return 0;
- }
- break;
- case WM_SYSCOMMAND:
- if(wParam>=IDM_MYSYSCOMMANDS&&wParam<=(IDM_MYSYSCOMMANDS+max_index_added)){
- #ifdef FAKE_LAUNCHES
- MessageBox(hwnd,show_exe_data(wParam-IDM_MYSYSCOMMANDS),"Doing a command",MB_OK|MB_ICONINFORMATION);
- #else
- start_program(wParam-IDM_MYSYSCOMMANDS);
- #endif
- return 0;
- }
- else switch(wParam){
- case IDM_ABOUT:
- MessageBox(hwnd,copyright,"About ButtonGo",MB_OK|MB_ICONINFORMATION);
- return 0;
- case IDM_HELP:
- MessageBox(hwnd,helpstring,"ButtonGo Help",MB_OK|MB_ICONINFORMATION);
- return 0;
- case IDM_ONTOP:
- if(MF_CHECKED&GetMenuState(gm,IDM_ONTOP,MF_BYCOMMAND)){
- CheckMenuItem(gm,IDM_ONTOP,MF_BYCOMMAND|MF_UNCHECKED);
- SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
- }
- else{
- CheckMenuItem(gm,IDM_ONTOP,MF_BYCOMMAND|MF_CHECKED);
- SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
- }
- return 0;
- }
- break;
- case WM_LBUTTONDOWN:
- {
- int b=button_mouse_is_in(lParam);
- if(b!=-1){
- mouse_button_number=b;
- wsprintf(scratch,"%s (%s)",(LPSTR)gf.get_item_name(b),(LPSTR)gf.get_item_command_nopath(b));
- SetWindowText(hwnd,scratch);
- mouse_down=1;
- ok_to_launch=1;
- InvalidateRect(hwnd,NULL,FALSE);
- UpdateWindow(hwnd);
- SetCapture(hwnd);
- return 0;
- }
- }
- break;
- case WM_CANCELMODE:
- if(mouse_down){
- restore_mouse_normalcy();
- return 0;
- }
- break;
- case WM_MOUSEMOVE:
- if(mouse_down){
- int b=button_mouse_is_in(lParam);
- if(b!=mouse_button_number){
- ok_to_launch=0;
- mouse_button_number=b;
- if(b!=-1){
- wsprintf(scratch,"%s (%s)",(LPSTR)gf.get_item_name(b),(LPSTR)gf.get_item_command_nopath(b));
- SetWindowText(hwnd,scratch);
- }
- else{
- SetWindowText(hwnd,WindowTitle);
- }
- InvalidateRect(hwnd,NULL,FALSE);
- UpdateWindow(hwnd);
- }
- return 0;
- }
- break;
- case WM_LBUTTONUP:
- if(mouse_down){
- int b=button_mouse_is_in(lParam),its_a_go=0;
- if(ok_to_launch&&b==mouse_button_number){
- its_a_go=1;
- }
- restore_mouse_normalcy();
- if(its_a_go){
- #ifdef FAKE_LAUNCHES
- MessageBox(hwnd,show_exe_data(b),"Mousing a command",MB_OK|MB_ICONINFORMATION);
- #else
- start_program(b);
- #endif
- }
- return 0;
- }
- break;
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- HDC hdc=BeginPaint(hwnd,&ps);
- if(hdc!=NULL){
- HDC hdcmem=CreateCompatibleDC(hdc);
- if(hdcmem!=NULL){
- HBITMAP hbmOld=SelectObject(hdcmem,hbmNow);
- get_right_bitmap(hdcmem);
- BitBlt(hdc,0,0,bitmap_width,bitmap_height,hdcmem,0,0,SRCCOPY);
- SelectObject(hdcmem,hbmOld);
- DeleteDC(hdcmem);
- }
- }
- EndPaint(hwnd,&ps);
- }
- return 0;
- case WM_DESTROY:
- if(hbmUp !=NULL){DeleteObject(hbmUp );hbmUp =NULL;}
- if(hbmDown!=NULL){DeleteObject(hbmDown);hbmDown=NULL;}
- if(hbmNow !=NULL){DeleteObject(hbmNow );hbmNow =NULL;}
- if(should_save_position_data){
- ini.write_screen_numbers(szFile,hwnd,MF_CHECKED&GetMenuState(gm,IDM_ONTOP,MF_BYCOMMAND)?1:0);
- }
- PostQuitMessage(0);
- return 0;
- case WM_ENDSESSION:
- if(wParam&&should_save_position_data){
- ini.write_screen_numbers(szFile,hwnd,MF_CHECKED&GetMenuState(gm,IDM_ONTOP,MF_BYCOMMAND)?1:0);
- }
- else break;
- return 0;
- }
- return DefWindowProc(hwnd,message,wParam,lParam);
- }
- int GetFileDataLoaded(LPSTR lpszCmdLine){
- OPENFILENAME ofn;
- char szDirName[256];
- GetWindowsDirectory(szDirName,sizeof(szDirName));
- szFile[0]=0;
- GetFilenameFromCmdLine(lpszCmdLine,szDirName,szFile);
- if(szFile[0]==0){
- memset(&ofn,0,sizeof(ofn));
- ofn.lStructSize=sizeof(ofn);
- ofn.hwndOwner=main_hwnd;
- ofn.lpstrFilter="Group Files\0*.GRP\0";
- ofn.nFilterIndex=1;
- ofn.lpstrFile=szFile;
- ofn.nMaxFile=sizeof(szFile);
- ofn.lpstrInitialDir=szDirName;
- ofn.lpstrTitle="Choose .GRP file for ButtonGo";
- ofn.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
- ofn.lpstrDefExt="GRP";
- // let's make sure COMMDLG.DLL is here so unfriendly system message doesn't show up
- // on GetOpenFileName() call in Win 3.0
- // doing LoadLibrary()/GetProcAddress() shuffle to avoid needing COMMDLG.DLL just to load
- int got_commdlg=0;
- UINT old_sem=SetErrorMode(SEM_NOOPENFILEERRORBOX);
- HINSTANCE h=LoadLibrary("COMMDLG.DLL");
- if(h>=HINSTANCE_ERROR){ // ok the DLL is there
- BOOL(WINAPI*lpGetOpenFileName)(OPENFILENAME FAR*)=(BOOL(WINAPI*)(OPENFILENAME FAR*))GetProcAddress(h,"GetOpenFileName");
- if(lpGetOpenFileName!=NULL){
- got_commdlg=1;
- if(!(*lpGetOpenFileName)(&ofn)){
- FreeLibrary(h);
- SetErrorMode(old_sem);
- return NULL; // user canceled, so bail out...
- }
- }
- FreeLibrary(h);
- }
- SetErrorMode(old_sem);
- if(!got_commdlg){
- errscreen<<"COMMDLG.DLL should be in your WINDOWS\\SYSTEM directory\n\n";
- errscreen<<"Until you get that file installed, you'll have to specify a .GRP ";
- errscreen<<"filename on BtnGo's command line";
- errscreen.show("Quitting");
- return NULL;
- }
- }
- #ifdef DEBUG_SCREENS
- screen<<"File is \""<<szFile<<"\"\n";
- #endif
- { // get to all caps so .INI file works right (same every time even if typed)
- char *cp=szFile;
- while(*cp){
- *cp=toupper((int)*cp);
- cp++;
- }
- }
- gf.set_filename(szFile);
- if(!gf.openfile()){
- errscreen<<"File is "<<szFile<<"\n"<<"Could not open file\n";
- errscreen.show();
- return NULL;
- }
- gf.readheader();
- #ifdef DEBUG_SCREENS
- screen<<"header read was "<<(gf.error()?"not ":"")<<"successful\n";
- screen<<"there are "<<gf.itemsleft()<<" items to process\n";
- #endif
- int added_some=0;
- for(int x=0;x<gf.itemsleft();x++){
- if(gf.error()){
- errscreen<<"aborting due to error\n";
- errscreen.show();
- break;
- }
- if(gf.showitem(x)){
- actual_buttons++;
- char __far *ptr=gf.get_item_name(x);
- while(ptr!=NULL&&isspace(*ptr))ptr++;
- if(ptr!=NULL&&*ptr){ // don't add to system menu if name was all spaces
- if(!(added_some%9))AppendMenu(gm,MF_MENUBARBREAK,0,NULL);
- added_some++;
- AppendMenu(gm,MF_STRING,IDM_MYSYSCOMMANDS+x,ptr);
- max_index_added=max_index_added>(unsigned int)x?max_index_added:(unsigned int)x;
- }
- }
- }
- #ifdef DEBUG_SCREENS
- screen.show("All Done");
- #endif
- return 1;
- }
- int CreateBitmaps(void){
- /*
- This function creates a set of three bitmaps. The first bitmap, the handle to which is
- called hbmUp, is the bitmap that show all the buttons in their up (normal) state.
- The second, hbmDown, shows all the buttons in their down state. The last, hbmNow, is
- the *current* picture, which is normally all up (a copy of hbmUp) but may include
- exactly one button from hbmDown.
-
- The bitmaps are created to fit exactly into the client area of the main window.
- So though the main window has NULL for hbrBackground, the area should look fine due
- to WM_PAINT always repainting the entire thing. The lack of erase should reduce flicker.
- */
- int width,height=icon_height+5,retval=0;
- HDC hdc=NULL,memhdc=NULL,icondc=NULL,bwdc=NULL;
- HBRUSH hbrFace=NULL,hbrOld=NULL;
- HPEN hpFace=NULL,hpHighlight=NULL,hpShadow=NULL,hpBlack=NULL,hpOld=NULL;
- HBITMAP hbmOld=NULL;
- {
- int temp=GetSystemMetrics(SM_CXMIN); // window can't be arbitrarily small
- width=actual_buttons*BUTTON_WIDTH;
- width=width>temp?width:temp;
- }
- bitmap_width=width;
- bitmap_height=height;
- // create bitmaps
- hbmUp=CreateBitmap(width,height,gf.get_icon_planes(),gf.get_icon_pixelbits(),NULL);
- hbmDown=CreateBitmap(width,height,gf.get_icon_planes(),gf.get_icon_pixelbits(),NULL);
- hbmNow=CreateBitmap(width,height,gf.get_icon_planes(),gf.get_icon_pixelbits(),NULL);
- if(hbmUp==NULL||hbmDown==NULL||hbmNow==NULL)return 0;
- // create display context
- if((hdc=CreateDC("DISPLAY",NULL,NULL,NULL))==NULL)goto bailout;
- // create compatible DC and select 'up' bitmap
- if(NULL==(memhdc=CreateCompatibleDC(hdc)))goto bailout;
- hbmOld=SelectObject(memhdc,hbmUp);
- // create DC for icon
- icondc=CreateCompatibleDC(hdc);
- if(icondc==NULL)goto bailout;
- // create brush for button faces and select it
- if(NULL==(hbrFace =CreateSolidBrush(GetSysColor(COLOR_BTNFACE ))))goto bailout;
- hbrOld=SelectObject(memhdc,hbrFace);
- // create pens for black, button faces, edges, select face color
- if(NULL==(hpBlack=GetStockObject(BLACK_PEN)))goto bailout;
- if(NULL==(hpFace =CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNFACE ))))goto bailout;
- if(winver>=0x30A){
- if(NULL==(hpHighlight=CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNHIGHLIGHT))))goto bailout;
- }
- else{
- if(NULL==(hpHighlight=CreatePen(PS_SOLID,1,RGB(255,255,255))))goto bailout;
- }
- if(NULL==(hpShadow =CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW ))))goto bailout;
- hpOld=SelectObject(memhdc,hpFace);
- Rectangle(memhdc,0,0,width,height); // faces, up map
- { // button edges, up map
- int f_ofset,x_offset,x_size,y_size;
- for(f_ofset=0,x_offset=0;f_ofset<actual_buttons;f_ofset++,x_offset+=(5+icon_width)){
- int oldstretchmode=SetStretchBltMode(memhdc,STRETCH_DELETESCANS);
- { // get AND data
- HBITMAP x=gf.get_fill_item_and_bitmap(f_ofset,x_size,y_size);
- if(x!=NULL){
- x=SelectObject(icondc,x); // save old one...
- StretchBlt(memhdc,x_offset+2,2,icon_width,icon_height,icondc,0,0,x_size,y_size,SRCAND);
- x=SelectObject(icondc,x); // get new one back
- DeleteObject(x); // and delete it
- }
- }
- { // get XOR data
- HBITMAP x=gf.get_fill_item_xor_bitmap(f_ofset,x_size,y_size);
- if(x!=NULL){
- x=SelectObject(icondc,x); // save old one...
- StretchBlt(memhdc,x_offset+2,2,icon_width,icon_height,icondc,0,0,x_size,y_size,SRCINVERT);
- x=SelectObject(icondc,x); // get new one back
- DeleteObject(x); // and delete it
- }
- }
- SetStretchBltMode(memhdc,oldstretchmode);
- SelectObject(memhdc,hpBlack); // draw black lines
- MoveTo(memhdc,x_offset ,1);
- LineTo(memhdc,x_offset ,icon_height+4);
- MoveTo(memhdc,x_offset+icon_width+4 ,1);
- LineTo(memhdc,x_offset+icon_width+4 ,icon_height+4);
- MoveTo(memhdc,x_offset+1 ,0);
- LineTo(memhdc,x_offset+icon_width+4 ,0);
- MoveTo(memhdc,x_offset+1 ,icon_height+4);
- LineTo(memhdc,x_offset+icon_width+4 ,icon_height+4);
- SelectObject(memhdc,hpHighlight); // draw highlights
- MoveTo(memhdc,x_offset+1 ,1);
- LineTo(memhdc,x_offset+icon_width+3 ,1);
- MoveTo(memhdc,x_offset+1 ,2);
- LineTo(memhdc,x_offset+1 ,icon_height+3);
- SelectObject(memhdc,hpShadow); // draw shadows
- MoveTo(memhdc,x_offset+icon_width+2 ,2);
- LineTo(memhdc,x_offset+icon_width+2 ,icon_height+4);
- MoveTo(memhdc,x_offset+icon_width+3 ,1);
- LineTo(memhdc,x_offset+icon_width+3 ,icon_height+4);
- MoveTo(memhdc,x_offset+2 ,icon_height+2);
- LineTo(memhdc,x_offset+icon_width+2 ,icon_height+2);
- MoveTo(memhdc,x_offset+1 ,icon_height+3);
- LineTo(memhdc,x_offset+icon_width+2 ,icon_height+3);
- }
- }
- // now do 'down' bitmap
- SelectObject(memhdc,hbmDown);
- SelectObject(memhdc,hpFace);
- Rectangle(memhdc,0,0,width,height); // faces, down map
- { // button edges, down map
- int f_ofset,x_offset,x_size,y_size;
- for(f_ofset=0,x_offset=0;f_ofset<actual_buttons;f_ofset++,x_offset+=(5+icon_width)){
- int shrinkage=(icon_width*2)/10,oldstretchmode=SetStretchBltMode(memhdc,STRETCH_DELETESCANS);
- { // get AND data
- HBITMAP x=gf.get_fill_item_and_bitmap(f_ofset,x_size,y_size);
- if(x!=NULL){
- x=SelectObject(icondc,x); // save old one...
- StretchBlt(memhdc,x_offset+2+shrinkage,2+shrinkage,icon_width-shrinkage,icon_height-shrinkage,icondc,0,0,x_size,y_size,SRCAND);
- x=SelectObject(icondc,x); // get new one back
- DeleteObject(x); // and delete it
- }
- }
- { // get XOR data
- HBITMAP x=gf.get_fill_item_xor_bitmap(f_ofset,x_size,y_size);
- if(x!=NULL){
- x=SelectObject(icondc,x); // save old one...
- StretchBlt(memhdc,x_offset+2+shrinkage,2+shrinkage,icon_width-shrinkage,icon_height-shrinkage,icondc,0,0,x_size,y_size,SRCINVERT);
- x=SelectObject(icondc,x); // get new one back
- DeleteObject(x); // and delete it
- }
- }
- SetStretchBltMode(memhdc,oldstretchmode);
- SelectObject(memhdc,hpBlack); // draw black lines
- MoveTo(memhdc,x_offset ,1);
- LineTo(memhdc,x_offset ,icon_height+4);
- MoveTo(memhdc,x_offset+icon_width+4 ,1);
- LineTo(memhdc,x_offset+icon_width+4 ,icon_height+4);
- MoveTo(memhdc,x_offset+1 ,0);
- LineTo(memhdc,x_offset+icon_width+4 ,0);
- MoveTo(memhdc,x_offset+1 ,icon_height+4);
- LineTo(memhdc,x_offset+icon_width+4 ,icon_height+4);
- SelectObject(memhdc,hpShadow); // draw shadows
- MoveTo(memhdc,x_offset+1 ,1);
- LineTo(memhdc,x_offset+icon_width+4 ,1);
- MoveTo(memhdc,x_offset+1 ,2);
- LineTo(memhdc,x_offset+1 ,icon_height+4);
- MoveTo(memhdc,x_offset+2 ,2);
- LineTo(memhdc,x_offset+icon_width+4 ,2);
- MoveTo(memhdc,x_offset+2 ,3);
- LineTo(memhdc,x_offset+2 ,icon_height+4);
- }
- }
- retval=1;
- bailout:
- if(icondc!=NULL)DeleteDC(icondc);
- if(hpShadow!=NULL)SelectObject(memhdc,hpOld);
- if(hpShadow !=NULL)DeleteObject(hpShadow );
- if(hpHighlight!=NULL)DeleteObject(hpHighlight);
- if(hpFace !=NULL)DeleteObject(hpFace );
- if(hbrFace!=NULL){
- SelectObject(memhdc,hbrOld);
- DeleteObject(hbrFace);
- }
- if(memhdc!=NULL){
- SelectObject(memhdc,hbmOld);
- DeleteDC(memhdc);
- }
- if(hdc!=NULL)DeleteDC(hdc);
- return retval;
- }
- int button_mouse_is_in(LONG lParam){
- if(actual_buttons==0||bitmap_width==0)return -1;
- int x=(int)LOWORD(lParam);
- int y=(int)HIWORD(lParam);
- if(y<0||y>=bitmap_height||x<0||x>=bitmap_width)return -1;
- x/=BUTTON_WIDTH;
- if(x>=actual_buttons)return -1;
- return x;
- }
- void restore_mouse_normalcy(void){
- if(mouse_down){
- ReleaseCapture();
- mouse_down=0;
- SetWindowText(main_hwnd,WindowTitle);
- InvalidateRect(main_hwnd,NULL,FALSE);
- UpdateWindow(main_hwnd);
- }
- }
- void get_right_bitmap(HDC hdc){
- /*
- draws appropriate bitmap into hdc if necessary, a memory DC
- the right-sized bitmap is already there
- */
- HDC hdc_source;
- HBITMAP hbmOld;
- if(!mouse_down||mouse_button_number==-1||
- !bitmap_width||!actual_buttons||
- (0==(hdc_source=CreateCompatibleDC(hdc)))){
- // just poke in the 'Up' bitmap
- SelectObject(hdc,hbmUp);
- }
- else{
- int left_edge=mouse_button_number*BUTTON_WIDTH;
- // first draw all 'up' buttons
- hbmOld=SelectObject(hdc_source,hbmUp);
- BitBlt(hdc,0,0,bitmap_width,bitmap_height,hdc_source,0,0,SRCCOPY);
- // now poke in the single 'down' button
- SelectObject(hdc_source,hbmDown);
- BitBlt(hdc,left_edge,0,BUTTON_WIDTH,bitmap_height,hdc_source,left_edge,0,SRCCOPY);
- SelectObject(hdc_source,hbmOld);
- DeleteDC(hdc_source);
- }
- }
- #ifdef FAKE_LAUNCHES
- char *show_exe_data(int offset){
- static char buf[300];
- wsprintf(buf,"Name \"%s\"\nExecutable \"%s\"\nDefault Directory \"%s\"\n%s minimized",
- gf.get_item_name(offset),
- gf.get_command(offset),
- gf.get_item_path(offset),
- (LPSTR)(gf.is_item_iconized(offset)?"Runs":"Does not run"));
- return buf;
- }
- #else
- void start_program(int offset){
- // launch the program, minimized if appropriate
- // report failures to the user
- UINT retval=0;
- if(winver>=0x30A){
- #ifdef SHOW_LAUNCHDATA
- errscreen<<"Ready to start\nget_item_command()=\""<<gf.get_item_command(offset);
- errscreen<<"\"\nget_item_parameters()=\""<<gf.get_item_parameters(offset);
- errscreen<<"\"\nget_item_default_dir()=\""<<gf.get_item_default_dir(offset);
- errscreen<<"\"\nitem is"<<(gf.is_item_iconized(offset)?"":" not")<<" iconized";
- errscreen.show();
- #endif
- UINT old_error_mode=SetErrorMode(SEM_NOOPENFILEERRORBOX);
- HINSTANCE s=LoadLibrary("SHELL.DLL");
- HINSTANCE (WINAPI*lpShellExecute)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,int);
- if(s>=HINSTANCE_ERROR)lpShellExecute=(HINSTANCE(WINAPI*)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,int))GetProcAddress(s,"ShellExecute");
- if(s>=HINSTANCE_ERROR&&lpShellExecute!=NULL){
- retval=(*lpShellExecute)(main_hwnd,NULL,
- gf.get_item_command(offset),gf.get_item_parameters(offset),
- gf.get_item_default_dir(offset),
- gf.is_item_iconized(offset)?SW_SHOWMINIMIZED:SW_SHOWNORMAL);
- }
- if(s>=HINSTANCE_ERROR)FreeLibrary(s);
- SetErrorMode(old_error_mode);
- }
- else{
- char buffer[250],*t;
- retval=2;
- LPSTR from=gf.get_item_default_dir(offset);
- if(from!=NULL){ // use path we stripped off originally
- lstrcpy(buffer,from);
- t=buffer;
- while(*t)t++;
- if(t[-1]!=':'&&t[-1]!='\\'){
- *t++='\\';
- *t=0;
- }
- lstrcpy(t,gf.get_item_command(offset));
- retval=WinExec(buffer,gf.is_item_iconized(offset)?SW_SHOWMINNOACTIVE:SW_SHOW);
- }
- if(retval==2){ // use 3.1-style command if present
- retval=WinExec(gf.get_item_command(offset),gf.is_item_iconized(offset)?SW_SHOWMINNOACTIVE:SW_SHOW);
- }
- if((retval==2)&&(gf.get_item_command(offset)!=gf.get_item_command_nopath(offset))){ // .EXE name only
- retval=WinExec(gf.get_item_command_nopath(offset),gf.is_item_iconized(offset)?SW_SHOWMINNOACTIVE:SW_SHOW);
- }
- }
- if(retval>=32)return; //success!
- char *p;
- switch(retval){
- case 0: p="System memory shortage or corrupt executable file"; break;
- case 2: p="File was not found"; break;
- case 3: p="Path was not found"; break;
- case 5: p="Attempt to dynamically link to a task, or sharing or network-protection error"; break;
- case 6: p="Library required separate data segments for each task"; break;
- case 8: p="Insufficient memory to start application"; break;
- case 10: p="Application can't run on this version of Windows"; break;
- case 11: p="Invalid executable file. Not a Windows application, or .EXE image error"; break;
- case 12: p="Application designed for a different operating system"; break;
- case 13: p="Application was designed for MS-DOS 4.0"; break;
- case 14: p="Unknown executable type"; break;
- case 15: p="Cannot run real-mode Windows applications"; break;
- case 16: p="Can't run multiple copies of this program (non-read-only multiple data segments)"; break;
- case 19: p="File must be decompressed before it is loaded"; break;
- case 20: p="One of the DLLs required to run this application was corrupt or otherwise invalid"; break;
- case 21: p="Application requires 32-bit extensions to Windows"; break;
- default: p="Unknown error"; break;
- }
- errscreen<<"Could not start "<<gf.get_item_command(offset)<<"\n\n"<<p;
- errscreen.show();
- }
- #endif
-